# >>> import this
# The Zen of Python, by Tim Peters
#
# Beautiful is better than ugly.
# Explicit is better than implicit.
# Simple is better than complex.
# Complex is better than complicated.
# Flat is better than nested.
# Sparse is better than dense.
# Readability counts.
# Special cases aren't special enough to break the rules.
# Although practicality beats purity.
# Errors should never pass silently. Unless explicitly silenced.
# In the face of ambiguity, refuse the temptation to guess.
# There should be one-- and preferably only one --obvious way to do it.
# Although that way may not be obvious at first unless you're Dutch.
# Now is better than never. Although never is often better than *right* now.
# If the implementation is hard to explain, it's a bad idea.
# If the implementation is easy to explain, it may be a good idea.
# Namespaces are one honking great idea -- let's do more of those!

# 优美胜于丑陋（Python 以编写优美的代码为目标）
# 明了胜于晦涩（优美的代码应当是明了的，命名规范，风格相似）
# 简洁胜于复杂（优美的代码应当是简洁的，不要有复杂的内部实现）
# 复杂胜于凌乱（如果复杂不可避免，那代码间也不能有难懂的关系，要保持接口简洁）
# 扁平胜于嵌套（优美的代码应当是扁平的，不能有太多的嵌套）
# 间隔胜于紧凑（优美的代码有适当的间隔，不要奢望一行代码解决问题）
# 可读性很重要（优美的代码是可读的）
# 即便假借特例的实用性之名，也不可违背这些规则（这些规则至高无上）
# 不要包容所有错误，除非你确定需要这样做（精准地捕获异常，不写 except:pass 风格的代码）
# 当存在多种可能，不要尝试去猜测
# 而是尽量找一种，最好是唯一一种明显的解决方案（如果不确定，就用穷举法）
# 虽然这并不容易，因为你不是 Python 之父（这里的 Dutch 是指 Guido ）
# 做也许好过不做，但不假思索就动手还不如不做（动手之前要细思量）
# 如果你无法向人描述你的方案，那肯定不是一个好方案；反之亦然（方案测评标准）
# 命名空间是一种绝妙的理念，我们应当多加利用（倡导与号召）

print("It's a big world, I use python!")

# classinfo: int，float，bool，complex，str(字符串)，list，dict(字典)，set，tuple
# 动态语言不用指定数据类型
print('\n动态语言不用指定数据类型 -----------')
a = 10
print(a)
a = "hello"
print(a)
a = True
print(a)
a = 1.23
print(a)

# 序列包括：字符串、元组和列表
# 打印、换行和连接
print('\n字符串初始化、换行、拼接 -----------')
s1 = "hello world"
print(s1)
s2 = "hello 'andy'"
print(s2)
s3 = 'hello "andy"'
print(s3)
s4 = 'hello \nlotus'
print(s4)
s5 = '''hello
u
sky'''
print(s5)
print('hello' + ' ' + "boy")

# 字符串转为整型
print('\n字符串与整型之间的转换 -------------')
a = ord('A')
print(a)
a = ord('中')
print(a)

# 整型转为字符串
a = chr(65)
print(a)
a = chr(20013)
print(a)
a = '\u4e2d\u6587'
print(a)

# 数据类型转换
print('\n数据类型之间的转换 -----------------')
print(int('123'))
print(int(1.23))
print(float('12.3'))
print(bool(123))
print(bool(''))
print(str(12.34))
print(str(True))

# Unicode的字符串编码 str->bytes
print('\n字符串编解码 ----------------------')
print('ABC'.encode('ASCII'))         # b'ABC'
print('中文'.encode('utf-8'))         # b'\xe4\xb8\xad\xe6\x96\x87'

# 特定编码的数据转为Unicode的字符串 bytes-str
print(b'ABC'.decode('ASCII'))                       # ABC
print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))  # 中文
print(b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore'))  # 如果bytes中只有一小部分无效的字节，可以传入errors='ignore'忽略错误的字节

# 取str长度，字符数
print('\n容器长度（字符长度或字节长度）---------')
print(len('ABC'))
print(len('中文'))

# 取bytes长度，字节数
print(len(b'ABC'))
print(len(b'\xe4\xb8\xad\xe6\x96\x87'))

# 字符串格式化显示
print('\n字符串格式化显示 --------------------')
print('Hi %s, you have %d dollars' % ('sky', 10000))
print('hi %s, you grade is %1.2f raised %d%% since last month' % ('sky', 97.123456, 10))

# list是一种有序的集合，可以随时添加和删除其中的元素
print('\nlist一种有序集合，可以随时添加和删除其中的元素')
mates = ['sky']
mates.append('cherry')
mates.insert(1, 'lotus')
mates.append("hello")
print('size = %d, mate[0] = %s, mate[1] = %s, mate[2] = %s, mate[3] = %s' % (len(mates), mates[0], mates[1], mates[2], mates[3]))
mates.pop(-1)
print('size = %d, mate[-1] = %s, mate[-2] = %s, mate[-3] = %s' % (len(mates), mates[-1], mates[-2], mates[-3]))

p = [True, 2]
mates.append(p)
print('size = %d, mates[3][0] = %s, mates[3][1] = %s' % (len(mates), mates[3][0], mates[3][1]))
print('size = %d, mates[-1][0] = %s, mates[-1][1] = %s' % (len(mates), mates[3][0], mates[3][1]))

# tuple有序列表叫元组, 一旦初始化就不能修改, 如果可能，能用tuple代替list就尽量用tuple
print('\ntuple有序列表叫元组, 一旦初始化就不能修改--')
t = (1,)
print(t)

t = ('a', 'b', ['c', 'd'], True, 2)
print(t)
t[2][0] = 'X'
t[2][1] = False
#t[3] = 5           第一维(turple)不可变，第二维(list)可变
print(t)

t = ('a', 'b', ('c', 'd'), True, 2)
#t[2][0] = 'X'
#t[2][1] = False
#t[3] = 5           第一维(turple)不可变，第二维(turple)不可变


# dic 在其他语言中也称为map，使用键-值（key-value）存储，具有极快的查找速度, key必须是不可变对象, 字符串、整数等都是不可变的， 因此，可以放心地作为key。而list是可变的，就不能作为key
print('\nmap使用key-value存储，key必须是不可变对象 --')
d = {'sky':91, 'lotus':92, 65:'A'}
d[65] = 'B'
print(d)
print('sky' in d)
print(d.get('lotus', -1))       # 如果不存在，指定一个默认值
d.pop(65)
print(d)

# set 没有重复的key, 如果重复，会被过滤掉, set和dict的唯一区别仅在于没有存储对应的value，但是，set的原理和dict一样，所以，同样不可以放入可变对象
# 因为无法判断两个可变对象是否相等， 也就无法保证set内部“不会有重复元素”
print('\nset没有重复的key, 如果重复，会被过滤掉 ------')
s = set([0, 1, 2, 3, 5, 4, 5, 6])
print(s)
s.add(8)
s.add(8)    # 可以重复添加，但不会有效果
print(s)    # {0, 1, 2, 3, 4, 5, 6, 8}
s.remove(8)

# 数学意义上的无序和无重复元素的集合，因此，两个set可以做数学意义上的交集、并集等操作
s1 = set([4, 5, 6, 7, 8, 9])
tmp = s & s1                # 交集
print("&: %s" % tmp)        # {4, 5, 6}
tmp = s | s1                # 并集
print("|: %s" % tmp)        # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}


# 可变对象与不可变对象
a = ['c', 'b', 'a']
a.sort()    # ['a', 'b', 'c']
print(a)    # list是可变对象，值会变化

a = 'abc'
print(a.replace('a', 'A'))  # Abc  会新创建一个新的字符串Abc返回
print(a)                    # abc  a是不可变对象，值不会变化


print(type(123))                    # <class 'int'>
print(type('123'))                  # <class 'str'>
print(type(True))                   # <class 'bool'>
print(type(12.34))                  # <class 'float'>
print(type(mates))                  # <class 'list'>
print(type(t))                      # <class 'tuple'>
print(type(int))                    # <class 'type'>
print(type(str))                    # <class 'type'>
print(type(list))                   # <class 'type'>
print(type(tuple))                  # <class 'type'>
print(isinstance(123, object))      # True
print(isinstance('123', object))    # True
print(isinstance(True, object))     # True
print(isinstance(12.34, object))    # True
print(isinstance(mates, object))    # True
print(isinstance(t, object))        # True
print(isinstance(type, object))     # True


# Python2.6 开始，新增了一种格式化字符串的函数 str.format()，它增强了字符串格式化的功能。相对于老版的%格式方法，它有很多优点
# 按照默认顺序，不指定位置，默认左对齐
print("{} {}".format("hello", "world"))         # hello world

# 设置指定位置，可以多次使用
print("{0} {1} {0}".format("hello", "world"))   # hello world hello

# 取10位左对齐，取10位右对齐
print('{:10s} {:>10s}'.format('hello', 'world'))   # hello            world

# 取10位中间对齐
print('{:^10s} {:^10s}'.format('hello', 'world'))  #  hello      world

# 取2位小数
PI = 3.1415926
print('{} is {:.2f}'.format(PI, PI))        # 3.1415926 is 3.14

# 右对齐, 取10位, 2位小数
print('{0} is {0:>10.2f}'.format(PI, PI))   # 3.1415926 is       3.14

# 使用map格式化
person = {"name": "sky", "age": 40}
print("my name is {name}, I am {age} years old".format(**person))   # my name is sky, I am 40 years old

# 通过list格式化
stu = ["sky", "linux", "MySQL", "Python"]
print("my name is {0[0]}, I love {0[1]}".format(stu))               # my name is sky, I love linux

# 通过元组格式化
info = 'superman', 66, 'pimiento'
print('my name is {}, I have {} million'.format(*info))                  # my name is superman, I have 66 million

# 通过元组+map格式化
print('my name is {2}, I am afraid of {name}'.format(*info, **person))   # my name is pimiento, I am afraid of sky

# 文件名
f = open('out.txt', 'w')
print('filename：{.name}'.format(f))     # filename：out.txt
f.close()

# 方括号用法：用列表传递位置参数
info = ['阿星', 9527]
food = ['霸王花', '爆米花']
# info是第0维，food是第1维
print('我叫{0[0]}, 警号{0[1]}, 爱吃{1[0]}'.format(info, food))    # 我叫阿星, 警号9527, 爱吃霸王花

# 方括号用法：用元组传递位置参数
food = ('僵尸', '脑子')
print('我叫{0[0]}, 年龄{1}, 爱吃{0[1]}'.format(food, 66))         # 我叫僵尸, 年龄66, 爱吃脑子

# 方括号用法：用字典传递位置参数
dic = dict(name='阿星', pid=9527)
print('我是{[name]}'.format(dic))                                # 我是阿星

# 多个替换字段，不能省略数字
print('我是{0[name]}, 警号{0[pid]}'.format(dic))                  # 我是阿星, 警号9527

# s 传递参数之前先对参数调用 str()
print('I am {!s}'.format('Bruce Lee 李小龙'))      # I am Bruce Lee 李小龙
# r 传递参数之前先对参数调用 repr()
print('I am {!r}'.format('Bruce Lee 李小龙'))      # I am 'Bruce Lee 李小龙'
# a 传递参数之前先对参数调用 ascii()
print('I am {!a}'.format('Bruce Lee 李小龙'))      # I am 'Bruce Lee \u674e\u5c0f\u9f99'

# b 类型：二进制
print('{0:b}'.format(3))            # 11
# c 类型：把整数转换成 unicode 字符
print('{:c}'.format(97))            # a
# d 类型：十进制整数
print('{:d}'.format(666))           # 666
# o 类型：八进制数
print('{:o}'.format(10))            # 12
# x 类型：十六进制数，a到f小写
print('{:x}'.format(15))            # f
# X 类型：十六进制数，A到F大写
print('{:X}'.format(15))            # F

D = 1234567.1234567
# e 类型：科学记数法, 默认精度为 6 位
print('{:e}'.format(D))       # 1.234567e+06
# 修改精度为 10 位
print('{:.10E}'.format(D))    # 1.2345671235E+06
# f 类型: 定点记法, 默认精度为 6 位
print('{:f}'.format(D))       # 1234567.123457
# 修改精度为 10 位
print('{:.10F}'.format(D))    # 1234567.1234567000
# g 类型: 通用 general 格式, 自动转换到 e 或者 f 格式
print('{:g}'.format(D))       # 1.23457e+06
print('{:G}'.format(D))       # 1.23457E+06
# n 类型: 数字 number 类型, 跟 g 一样, 只不过用本地化的分隔符来分隔数字
print('{:n}'.format(D))       # 1.23457e+06
# % 类型: 百分号类型, 会将数字乘以 100, 然后以 f 定点 fixed-point 格式显示, 最后加上一个百分号 %
print('{:%}'.format(0.83))    # 83.000000%

